package com.xhj.mybatis.builder.annotation;

import com.xhj.mybatis.annotations.Delete;
import com.xhj.mybatis.annotations.Insert;
import com.xhj.mybatis.annotations.Select;
import com.xhj.mybatis.annotations.Update;
import com.xhj.mybatis.binding.MapperMethod;
import com.xhj.mybatis.builder.MapperBuilderAssistant;
import com.xhj.mybatis.builder.xml.XMLMapperBuilder;
import com.xhj.mybatis.executor.keygen.Jdbc3KeyGenerator;
import com.xhj.mybatis.executor.keygen.KeyGenerator;
import com.xhj.mybatis.executor.keygen.NoKeyGenerator;
import com.xhj.mybatis.io.Resources;
import com.xhj.mybatis.mapping.ResultMapping;
import com.xhj.mybatis.mapping.SqlCommandType;
import com.xhj.mybatis.mapping.SqlSource;
import com.xhj.mybatis.reflection.TypeParameterResolver;
import com.xhj.mybatis.scripting.LanguageDriver;
import com.xhj.mybatis.session.Configuration;
import com.xhj.mybatis.session.ResultHandler;
import com.xhj.mybatis.session.RowBounds;
import org.dom4j.DocumentException;

import java.io.IOException;
import java.io.InputStream;
import java.lang.annotation.Annotation;
import java.lang.reflect.*;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * MapperAnnotationBuilder
 *
 * @author XJks
 * @description 基于注解的映射器构建器，用于解析和处理使用注解方式定义的SQL映射。
 */
public class MapperAnnotationBuilder {

    /**
     * 定义一个静态常量集合，包含所有 SQL 语句相关的注解类型（如 @Select、@Update、@Insert、@Delete等）
     */
    private static final Set<Class<? extends Annotation>> statementAnnotationTypes = Stream
            // 将常用的 SQL 注解类（@Select、@Update、@Insert、@Delete等）放入 Stream
            .of(Select.class, Update.class, Insert.class, Delete.class)
            // 收集到一个 Set 集合中，方便后续判断和遍历
            .collect(Collectors.toSet());

    /**
     * 保存 MyBatis 的全局配置对象，包含所有配置信息
     */
    private final Configuration configuration;

    /**
     * 辅助类，用于构建和注册 Mapper 的相关信息（如命名空间、语句等）
     */
    private final MapperBuilderAssistant assistant;

    /**
     * 当前正在解析的 Mapper 接口的 Class 对象
     */
    private final Class<?> type;

    /**
     * 构造方法，初始化 MapperAnnotationBuilder
     *
     * @param configuration 全局配置对象
     * @param type          当前 Mapper 接口的 Class 类型
     */
    public MapperAnnotationBuilder(Configuration configuration, Class<?> type) {
        // 生成资源名，用于标识当前 Mapper
        String resource = type.getName().replace('.', '/') + ".java (best guess)";
        // 创建 MapperBuilderAssistant 辅助对象，传入配置和资源名
        this.assistant = new MapperBuilderAssistant(configuration, resource);
        // 保存全局配置对象
        this.configuration = configuration;
        // 保存当前 Mapper 的 Class 类型
        this.type = type;
    }

    /**
     * 解析当前 Mapper 接口的注解，生成对应的映射信息（如 MappedStatement、ResultMap 等）
     */
    public void parse() {
        // 获取当前 Mapper 接口的类名字符串，作为资源标识
        String resource = type.toString();
        // 如果该资源还没有被加载过
        if (!configuration.isResourceLoaded(resource)) {
            // 加载对应的 XML 映射文件（如果有）
            loadXmlResource();
            // 标记该资源已被加载，防止重复加载
            configuration.addLoadedResource(resource);
            // 设置当前命名空间为该 Mapper 的全限定类名
            assistant.setCurrentNamespace(type.getName());
            // todo:源码这里存在解析缓存注解的逻辑，暂未实现。
            // 遍历该接口的所有方法
            for (Method method : type.getMethods()) {
                // 过滤掉 bridge 方法和 default 方法（如接口的默认实现）
                if (!canHaveStatement(method)) {
                    continue;
                }
                // 如果方法上有 @Select 注解，解析并生成对应的 ResultMap。todo:源码这里存在其他注解的处理逻辑，暂未实现。
                if (getAnnotationWrapper(method, false, Select.class).isPresent()) {
                    // 解析并生成对应的 ResultMap
                    parseResultMap(method);
                }
                // 解析方法上的 SQL 注解，生成 MappedStatement
                parseStatement(method);
            }
        }
    }

    /**
     * 尝试加载与当前 Mapper 接口对应的 XML 映射文件
     */
    private void loadXmlResource() {
        /**
         * todo:
         *  源码说明:
         *      1.Spring 可能无法获取真实的资源名，因此这里用一个标志避免重复加载
         *      2.这个标志会在 XMLMapperBuilder#bindMapperForNamespace 方法中设置
         */
        if (!configuration.isResourceLoaded("namespace:" + type.getName())) {
            // 构造 XML 文件的资源路径，例如 com/example/Mapper.xml
            String xmlResource = type.getName().replace('.', '/') + ".xml";
            // 尝试从当前类的资源路径下加载 XML 文件
            InputStream inputStream = type.getResourceAsStream("/" + xmlResource);
            if (inputStream == null) {
                // 如果没找到，说明 XML 不在当前模块，尝试从 classpath 下查找
                try {
                    inputStream = Resources.getResourceAsStream(xmlResource);
                } catch (IOException e2) {
                    // 忽略异常，因为 XML 不是必须的
                }
            }
            // 如果找到了 XML 文件的输入流
            if (inputStream != null) {
                // 创建 XMLMapperBuilder 解析 XML 映射文件
                XMLMapperBuilder xmlParser = null;
                try {
                    xmlParser = new XMLMapperBuilder(
                            assistant.getConfiguration(),
                            xmlResource,
                            inputStream
                    );
                } catch (DocumentException e) {
                    throw new RuntimeException(e);
                }
                // 解析 XML 文件，注册映射信息
                xmlParser.parse();
            }
        }
    }

    /**
     * 解析方法上的注解，生成对应的 ResultMap，并返回其 ID
     *
     * @param method 要解析的方法
     * @return 生成的 ResultMap ID
     */
    private String parseResultMap(Method method) {
        // 获取方法的返回类型（如 User.class），用于后续映射
        Class<?> returnType = getReturnType(method);
        // 生成 ResultMap 的唯一 ID
        String resultMapId = generateResultMapName(method);
        // 应用并注册 ResultMap，包含返回类型、参数、字段映射和多态信息
        applyResultMap(resultMapId, returnType);
        // 返回生成的 ResultMap ID，供后续使用
        return resultMapId;
    }

    /**
     * 生成 ResultMap 的唯一名称（ID），用于标识每个方法对应的结果映射
     *
     * @param method 要生成 ResultMap 名称的方法
     * @return 生成的 ResultMap 名称
     */
    private String generateResultMapName(Method method) {
        // 用于拼接参数类型的字符串
        StringBuilder suffix = new StringBuilder();
        // 遍历方法的所有参数类型
        for (Class<?> c : method.getParameterTypes()) {
            // 每个参数类型前加一个“-”，后面拼接参数类型的简单类名
            suffix.append("-");
            suffix.append(c.getSimpleName());
        }
        // 如果方法没有参数（suffix 为空），则补充“-void”表示无参数
        if (suffix.length() < 1) {
            suffix.append("-void");
        }
        // 返回格式：全限定类名 + "." + 方法名 + 参数类型后缀
        // 例如 com.example.UserMapper.selectUser-Integer
        return type.getName() + "." + method.getName() + suffix;
    }

    /**
     * 应用并注册 ResultMap（结果映射），用于描述 SQL 查询结果如何映射到 Java 对象。
     *
     * @param resultMapId ResultMap 的唯一标识符
     * @param returnType  查询方法的返回类型
     */
    private void applyResultMap(String resultMapId, Class<?> returnType) {
        // 创建一个用于存放所有字段映射关系的列表
        List<ResultMapping> resultMappings = new ArrayList<>();
        // 调用助手注册 ResultMap，包括 ID、返回类型、多字段映射等
        assistant.addResultMap(resultMapId, returnType, resultMappings, null);
    }

    /**
     * 解析方法上的 SQL 注解，生成对应的 MappedStatement（SQL 映射语句）
     *
     * @param method 要解析的方法
     */
    void parseStatement(Method method) {
        // 获取方法的参数类型（排除 RowBounds、ResultHandler 等特殊参数）
        final Class<?> parameterTypeClass = getParameterType(method);
        // 获取该方法上指定的 LanguageDriver（如未指定则用默认的）
        final LanguageDriver languageDriver = getLanguageDriver(method);

        // 查找方法上的 SQL 语句注解（如 @Select、@Update 等），并用 Optional 包装
        getAnnotationWrapper(method, true, statementAnnotationTypes).ifPresent(statementAnnotation -> {
            // 根据注解内容、参数类型、语言驱动、方法，构建 SqlSource（SQL 源对象）
            final SqlSource sqlSource = buildSqlSource(statementAnnotation.getAnnotation(), parameterTypeClass, languageDriver, method);
            // 获取注解对应的 SQL 命令类型（SELECT/INSERT/UPDATE/DELETE）
            final SqlCommandType sqlCommandType = statementAnnotation.getSqlCommandType();
            // todo:源码这里存在解析方法上的 @Options 注解的逻辑，暂未实现。
            // 生成 MappedStatement 的唯一 ID（全限定类名.方法名）
            final String mappedStatementId = type.getName() + "." + method.getName();

            // 定义主键生成器相关变量
            final KeyGenerator keyGenerator;
            String keyProperty = null;
            String keyColumn = null;
            // 如果是 INSERT 或 UPDATE 语句，处理主键生成逻辑
            if (SqlCommandType.INSERT.equals(sqlCommandType) || SqlCommandType.UPDATE.equals(sqlCommandType)) {
                // todo:源码这里存在解析相关注解获取主键配置信息和主键生成器的逻辑，暂未实现，这里进行简化处理，待完善。
                keyGenerator = configuration.isUseGeneratedKeys() ? Jdbc3KeyGenerator.INSTANCE : new NoKeyGenerator();
            } else {
                // 不是 INSERT/UPDATE，主键生成器为 NoKeyGenerator
                keyGenerator = NoKeyGenerator.INSTANCE;
            }

            // todo:源码这里存在解析其他可选参数的逻辑，暂未实现。
            // 是否为 SELECT 查询
            boolean isSelect = sqlCommandType == SqlCommandType.SELECT;
            // 非 SELECT 默认刷新缓存
            boolean flushCache = !isSelect;
            // 处理结果映射 ID
            String resultMapId = null;
            if (isSelect) {
                // 自动生成 ResultMap 名称
                resultMapId = generateResultMapName(method);
            }

            // 注册 MappedStatement（SQL 映射语句）到 MyBatis 配置
            assistant.addMappedStatement(
                    mappedStatementId,
                    sqlSource,
                    sqlCommandType,
                    parameterTypeClass,
                    resultMapId,
                    getReturnType(method),
                    flushCache,
                    keyGenerator,
                    keyProperty,
                    keyColumn,
                    statementAnnotation.getDatabaseId(),
                    languageDriver
            );
        });
    }

    /**
     * 获取方法上指定的 LanguageDriver（SQL 语言驱动器），用于解析 SQL 语句
     *
     * @param method 要解析的方法
     * @return 对应的 LanguageDriver 实例
     */
    private LanguageDriver getLanguageDriver(Method method) {
        // todo:源码这里存在解析方法上 @Lang 注解的逻辑，暂未实现。
        // 用于保存 LanguageDriver 的类型
        Class<? extends LanguageDriver> langClass = null;
        // 从全局配置中获取对应的 LanguageDriver 实例（如果 langClass 为 null，则返回默认的）
        return configuration.getLanguageDriver(langClass);
    }

    /**
     * 1.推断方法的参数类型（排除特殊参数 RowBounds 和 ResultHandler）
     * 2.如果有多个普通参数，则返回 ParamMap.class，表示参数为 Map 类型
     *
     * @param method 要解析的方法
     * @return 方法的参数类型
     */
    private Class<?> getParameterType(Method method) {
        // 用于保存最终推断出来的参数类型
        Class<?> parameterType = null;
        // 获取方法的所有参数类型数组
        Class<?>[] parameterTypes = method.getParameterTypes();
        // 遍历每一个参数类型
        for (Class<?> currentParameterType : parameterTypes) {
            // 跳过 RowBounds 和 ResultHandler 这两种特殊参数类型
            if (!RowBounds.class.isAssignableFrom(currentParameterType) && !ResultHandler.class.isAssignableFrom(currentParameterType)) {
                // 如果还没有设置参数类型，则用当前参数类型
                if (parameterType == null) {
                    parameterType = currentParameterType;
                } else {
                    // TODO:如果已经有一个参数类型了，说明有多个普通参数。按 MyBatis 约定，多个参数时用 ParamMap 作为参数类型
                    parameterType = MapperMethod.ParamMap.class;
                }
            }
        }
        // 返回最终推断出来的参数类型（可能为 null、某个类或 ParamMap.class）
        return parameterType;
    }

    /**
     * 获取方法的返回类型，支持泛型、集合、Optional、等多种情况
     *
     * @param method 要解析的方法
     * @return 方法的返回类型
     */
    private Class<?> getReturnType(Method method) {
        // 先获取方法声明的原始返回类型（如 List<User> 会得到 List.class）
        Class<?> returnType = method.getReturnType();
        // 解析泛型返回类型，得到更准确的类型信息
        Type resolvedReturnType = TypeParameterResolver.resolveReturnType(method, type);
        // 处理不同的返回类型情况
        if (resolvedReturnType instanceof Class) {
            // 如果解析结果是一个普通的类（非泛型）
            returnType = (Class<?>) resolvedReturnType;
            // 如果返回类型是数组，则取其元素类型（如 User[] 得到 User.class）
            if (returnType.isArray()) {
                returnType = returnType.getComponentType();
            }
            // 处理返回类型为 void 的特殊情况
            if (void.class.equals(returnType)) {
                // todo:源码这里存在解析方法上是否有 @ResultType 注解的处理逻辑
            }
        } else if (resolvedReturnType instanceof ParameterizedType) {
            // 如果返回类型是带泛型参数的类型（如 List<User>、Map<String, User> 等）
            ParameterizedType parameterizedType = (ParameterizedType) resolvedReturnType;
            // 获取原始类型（如 List.class、Map.class、Optional.class）
            Class<?> rawType = (Class<?>) parameterizedType.getRawType();
            // 如果是集合类型（如 List、Set），todo:源码这里存在处理 Cursor 的逻辑，暂未实现。
            if (Collection.class.isAssignableFrom(rawType)) {
                // 获取泛型参数（如 List<User> 的 User）
                Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
                if (actualTypeArguments != null && actualTypeArguments.length == 1) {
                    Type returnTypeParameter = actualTypeArguments[0];
                    // 如果泛型参数是普通类，直接赋值
                    if (returnTypeParameter instanceof Class<?>) {
                        returnType = (Class<?>) returnTypeParameter;
                        // 如果泛型参数本身还是带泛型的类型，取其原始类型
                    } else if (returnTypeParameter instanceof ParameterizedType) {
                        returnType = (Class<?>) ((ParameterizedType) returnTypeParameter).getRawType();
                        // 如果泛型参数是泛型数组类型（如 List<byte[]>），则构造对应的数组类型
                    } else if (returnTypeParameter instanceof GenericArrayType) {
                        Class<?> componentType = (Class<?>) ((GenericArrayType) returnTypeParameter).getGenericComponentType();
                        returnType = Array.newInstance(componentType, 0).getClass();
                    }
                }
            } else if (false && Map.class.isAssignableFrom(rawType)) {
                // todo:这里条件永远为 false，源码中是判断方法上是否有 @MapKey 注解，暂未实现该注解的处理逻辑。
                Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
                // Map 有两个泛型参数，取 value 的类型
                if (actualTypeArguments != null && actualTypeArguments.length == 2) {
                    Type returnTypeParameter = actualTypeArguments[1];
                    if (returnTypeParameter instanceof Class<?>) {
                        returnType = (Class<?>) returnTypeParameter;
                    } else if (returnTypeParameter instanceof ParameterizedType) {
                        returnType = (Class<?>) ((ParameterizedType) returnTypeParameter).getRawType();
                    }
                }
            } else if (Optional.class.equals(rawType)) {
                // 如果是 Optional 类型，取其泛型参数类型
                Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
                Type returnTypeParameter = actualTypeArguments[0];
                if (returnTypeParameter instanceof Class<?>) {
                    returnType = (Class<?>) returnTypeParameter;
                }
            }
        }
        // 返回最终推断出来的返回类型
        return returnType;
    }

    /**
     * 判断一个方法是否可以生成对应的 SQL 映射语句（MappedStatement）。
     * 只有非 bridge 方法且不是接口的 default 方法才可以生成 SQL 映射语句（MappedStatement）。
     *
     * @param method 要检查的方法
     * @return true 如果方法可以生成 SQL 映射语句，否则返回 false
     */
    private boolean canHaveStatement(Method method) {
        /**
         * 1.method.isBridge() 判断方法是否为 bridge 方法（编译器为泛型等生成的桥接方法，不能映射为 SQL）
         * 2.method.isDefault() 判断方法是否为接口的 default 方法（有默认实现的方法，不需要映射为 SQL）
         * 3.只有都不是时，才返回 true，表示该方法可以生成 SQL 映射
         */
        return !method.isBridge() && !method.isDefault();
    }

    /**
     * 根据注解类型构建对应的 SqlSource（SQL 源对象）。
     * 支持 @Select、@Update、@Insert、@Delete、@SelectKey 这几种注解，
     * 其余如 Provider 注解（如 @SelectProvider）则统一用 ProviderSqlSource 处理。
     *
     * @param annotation     方法上的注解对象
     * @param parameterType  SQL 参数类型
     * @param languageDriver SQL 语言驱动器
     * @param method         当前方法（Provider 注解需要用到）
     * @return 构建好的 SqlSource 对象
     */
    private SqlSource buildSqlSource(Annotation annotation, Class<?> parameterType, LanguageDriver languageDriver, Method method) {
        // 根据不同的注解类型，调用相应的构建逻辑
        if (annotation instanceof Select) {
            // 如果注解是 @Select，直接用注解里的 SQL 语句构建 SqlSource
            return buildSqlSourceFromStrings(((Select) annotation).value(), parameterType, languageDriver);
        } else if (annotation instanceof Update) {
            // 如果注解是 @Update，直接用注解里的 SQL 语句构建 SqlSource
            return buildSqlSourceFromStrings(((Update) annotation).value(), parameterType, languageDriver);
        } else if (annotation instanceof Insert) {
            // 如果注解是 @Insert，直接用注解里的 SQL 语句构建 SqlSource
            return buildSqlSourceFromStrings(((Insert) annotation).value(), parameterType, languageDriver);
        } else if (annotation instanceof Delete) {
            // 如果注解是 @Delete，直接用注解里的 SQL 语句构建 SqlSource
            return buildSqlSourceFromStrings(((Delete) annotation).value(), parameterType, languageDriver);
        } else {
            // 如果是其他情况，直接抛出异常，表示不支持该注解类型
            throw new RuntimeException("Unsupported annotation: " + annotation);
        }
    }

    /**
     * 根据 SQL 注解中的字符串数组，构建 SqlSource（SQL 源对象）。
     * 例如 @Select({"SELECT *", "FROM user"})，会把多行 SQL 拼成一行。
     *
     * @param strings            SQL 语句的字符串数组（通常注解里的 value 字段）
     * @param parameterTypeClass 参数类型的 Class，用于后续参数映射
     * @param languageDriver     MyBatis 的 SQL 语言驱动器，用于解析 SQL
     * @return 构建好的 SqlSource 对象，供 MyBatis 执行
     */
    private SqlSource buildSqlSourceFromStrings(String[] strings, Class<?> parameterTypeClass, LanguageDriver languageDriver) {
        /**
         * 1. 用空格把字符串数组拼接成一条完整的 SQL，并去掉首尾空格
         * 2. 调用 languageDriver 的 createSqlSource 方法，生成 SqlSource 对象
         */
        return languageDriver.createSqlSource(configuration, String.join(" ", strings).trim(), parameterTypeClass);
    }

    /**
     * 获取方法上的指定注解类型的包装器（可变参数版本），返回 Optional 包装的 AnnotationWrapper
     *
     * @param method         目标方法
     * @param errorIfNoMatch 是否在没有匹配注解时抛出错误
     * @param targetTypes    目标注解类型
     * @return Optional 包装的 AnnotationWrapper
     */
    private final Optional<AnnotationWrapper> getAnnotationWrapper(Method method, boolean errorIfNoMatch, Class<? extends Annotation>... targetTypes) {
        // 将可变参数转为集合，调用下一个重载方法
        return getAnnotationWrapper(method, errorIfNoMatch, Arrays.asList(targetTypes));
    }

    /**
     * 获取方法上的指定注解类型的包装器（集合参数版本），返回 Optional 包装的 AnnotationWrapper
     *
     * @param method         目标方法
     * @param errorIfNoMatch 是否在没有匹配注解时抛出错误
     * @param targetTypes    目标注解类型
     * @return Optional 包装的 AnnotationWrapper
     */
    private Optional<AnnotationWrapper> getAnnotationWrapper(Method method, boolean errorIfNoMatch, Collection<Class<? extends Annotation>> targetTypes) {
        // 获取当前配置中指定的 databaseId（用于多数据库环境区分）
        String databaseId = configuration.getDatabaseId();
        // 遍历所有目标注解类型，查找方法上是否有这些注解，并用 AnnotationWrapper 包装
        Map<String, AnnotationWrapper> statementAnnotations = targetTypes.stream()
                // 获取每种注解类型在方法上的所有注解，扁平化为一个流
                .flatMap(x -> Arrays.stream(method.getAnnotationsByType(x))).map(AnnotationWrapper::new)
                // 以 databaseId 作为 key，AnnotationWrapper 作为 value 收集到 Map
                .collect(Collectors.toMap(AnnotationWrapper::getDatabaseId, x -> x, (existing, duplicate) -> {
                    // 如果同一个 databaseId 存在多个注解，抛出异常
                    throw new RuntimeException(String.format("Detected conflicting annotations '%s' and '%s' on '%s'.",
                            existing.getAnnotation(), duplicate.getAnnotation(),
                            method.getDeclaringClass().getName() + "." + method.getName()));
                }));
        // 最终要返回的注解包装器
        AnnotationWrapper annotationWrapper = null;
        // 优先用当前 databaseId 查找
        if (databaseId != null) {
            annotationWrapper = statementAnnotations.get(databaseId);
        }
        // 如果没有找到，尝试用空字符串（默认）查找
        if (annotationWrapper == null) {
            annotationWrapper = statementAnnotations.get("");
        }
        // 如果要求必须有匹配注解，但没找到，且方法上确实有这些注解，则抛出异常
        if (errorIfNoMatch && annotationWrapper == null && !statementAnnotations.isEmpty()) {
            // 存在注解，但没有和当前 databaseId 匹配的
            throw new RuntimeException(
                    String.format(
                            "Could not find a statement annotation that correspond a current database or default statement on method '%s.%s'. Current database id is [%s].",
                            method.getDeclaringClass().getName(), method.getName(), databaseId));
        }
        // 返回 Optional 包装的结果（可能为 null）
        return Optional.ofNullable(annotationWrapper);
    }

    /**
     * 注解包装器类，用于统一处理不同 SQL 注解及其 SqlCommandType
     */
    private class AnnotationWrapper {
        /**
         * 注解对象本身
         */
        private final Annotation annotation;

        /**
         * 注解上的 databaseId 属性
         */
        private final String databaseId;

        /**
         * 注解对应的 SQL 命令类型（SELECT/INSERT/UPDATE/DELETE/UNKNOWN）
         */
        private final SqlCommandType sqlCommandType;

        /**
         * 构造方法，传入注解对象
         *
         * @param annotation 注解对象
         */
        AnnotationWrapper(Annotation annotation) {
            super();
            this.annotation = annotation;
            // 根据注解类型，提取 databaseId 和 sqlCommandType
            if (annotation instanceof Select) {
                databaseId = ((Select) annotation).databaseId();
                sqlCommandType = SqlCommandType.SELECT;
            } else if (annotation instanceof Update) {
                databaseId = ((Update) annotation).databaseId();
                sqlCommandType = SqlCommandType.UPDATE;
            } else if (annotation instanceof Insert) {
                databaseId = ((Insert) annotation).databaseId();
                sqlCommandType = SqlCommandType.INSERT;
            } else if (annotation instanceof Delete) {
                databaseId = ((Delete) annotation).databaseId();
                sqlCommandType = SqlCommandType.DELETE;
            } else {
                // 不是 SQL 语句注解，类型为 UNKNOWN
                sqlCommandType = SqlCommandType.UNKNOWN;
                // 其他注解没有 databaseId，默认为空字符串
                databaseId = "";
            }
        }

        /**
         * 获取注解对象
         *
         * @return 注解对象
         */
        Annotation getAnnotation() {
            return annotation;
        }

        /**
         * 获取 SQL 命令类型
         *
         * @return SQL 命令类型
         */
        SqlCommandType getSqlCommandType() {
            return sqlCommandType;
        }

        /**
         * 获取 databaseId
         *
         * @return databaseId
         */
        String getDatabaseId() {
            return databaseId;
        }
    }
}
